package top.dreamlove.core.ThreadDown;

import top.dreamlove.constant.Constant;
import top.dreamlove.utils.HttpUtils;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

/**
 * 多线程下载
 */


public class DownloadCallable implements Callable {

    private String url;//下载链接
    private Long downloadStart;//下载起始位置

    private Long downloadEnd;//下载结束位置

    private int partNumber;//标识数字(代表是第几块)

    private CountDownLatch latch;

    public DownloadCallable(String url, Long downloadStart, Long downloadEnd, int partNumber,CountDownLatch latch) {
        this.url = url;
        this.downloadStart = downloadStart;
        this.downloadEnd = downloadEnd;
        this.partNumber = partNumber;
        this.latch = latch;
    }

    @Override
    public Object call() throws Exception {
        //获取文件名
        String fileName = HttpUtils.getHttpFileName(url);
        //当前分块的名称
        fileName = fileName + Constant.prefix + partNumber;
        //下载路径
        fileName = Constant.Path + fileName;
        HttpURLConnection httpURLConnection = HttpUtils.getHttpURLConnection(url, downloadStart, downloadEnd);

        try(
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(inputStream);//缓冲流
                RandomAccessFile accessFile = new RandomAccessFile(fileName,"rw");
         ){
            byte[] buffer = new byte[1024 * 8];
            int len = -1;
            while ((len = bis.read(buffer)) != -1){
                // todo 改为非静态
                DownloadInfoThreadShowInfo.downloadedSize.add(len  / Constant.MB);
                accessFile.write(buffer,0,len);
            }
        }catch (Exception e){
            System.out.println("错误了" + e);
        }finally {
            //断开连接
            if(httpURLConnection != null){
                httpURLConnection.disconnect();
            }
            // 一定要保证每个线程执行完毕或者异常后调用countDown()方法
            // 如果不调用会导致其他线程一直等待, 无法继续执行
            // 建议放在finally代码块中, 防止异常情况下未调用countDown()方法
            latch.countDown();
        }

        return null;
    }
}
